package UIFree
{
	import UIUtils.uif_util;
	
	import flash.display.GradientType;
	import flash.display.InterpolationMethod;
	import flash.display.SpreadMethod;
	import flash.display.Sprite;
	import flash.filters.BevelFilter;
	import flash.filters.BitmapFilter;
	import flash.filters.BlurFilter;
	import flash.filters.DropShadowFilter;
	import flash.filters.GlowFilter;
	import flash.geom.Matrix;
	import flash.geom.Point;

	public class uif_draw extends Sprite {
		
		public static const TOP: int 	= 1;
		public static const RIGHT: int 	= 2;
		public static const BOTTOM: int = 3;
		public static const LEFT: int 	= 4;
		
		
		private var filterArray		: Array;
		private var shadow_filter	: DropShadowFilter;
		private var blur_filter		: BlurFilter;
		private var bevel_filter	: BevelFilter;
		private var glow_filter		: GlowFilter;
		
		public static const DRAWRECTMETHOD: String = 'draw_rect';
		public static const DRAWCIRCLEMETHOD: String = 'draw_circle';
		
		public function uif_draw() {
			super();
			filterArray = new Array();
		}
		
		public static function union(obj1: Object, obj2: Object): Object {
			return uif_util.union(obj1, obj2);
		}
		
		public static function applyOptions(obj: Object, options: Object, rewritePropery: Boolean = true): Object {
			for (var i: String in options) {
				if (rewritePropery || !obj.hasOwnProperty(i)) obj[i] = options[i];
			}
			return obj;
		}
		
		protected function getRounds(style: Object): Array {
			var l_rounds: Array = [0, 0, 0, 0];
			if (typeof(style.rounds) == 'number') {
				l_rounds[0] = style.rounds;
				l_rounds[1] = style.rounds;
				l_rounds[2] = style.rounds;
				l_rounds[3] = style.rounds;
			} else if (typeof(style.rounds) == 'object') l_rounds = style.rounds;
			return l_rounds;
		} 
		
		public function draw_rect(x: int, y: int, width: int, height: int, style: Object): void {
			begin2(style);
			var rounds: Array = getRounds(style);
			this.graphics.moveTo(x + rounds[0], y);
			this.graphics.lineTo(x + width - rounds[1], y);
			this.graphics.curveTo(x + width, y, x + width, y + rounds[1]);
			this.graphics.lineTo(x + width, y + height - rounds[2]);
			this.graphics.curveTo(x + width, y + height, x + width - rounds[2], y + height);
			this.graphics.lineTo(x + rounds[3], y + height);
			this.graphics.curveTo(x, y + height, x, y + height - rounds[3]);
			this.graphics.lineTo(x, y + rounds[0]);
			this.graphics.curveTo(x, y, x + rounds[0], y);
			if (style.fill_color) this.graphics.endFill();
		}
		
		public function draw_ellipse(x: int, y: int, width: int, height: int, style: Object): void {
			begin2(style);
			graphics.drawEllipse(x, y, width, height);
			if (style.fill_color) this.graphics.endFill();
		}
		
		public function draw_circle(x: int, y: int, width: int, height: int, style: Object): void {
			begin2(style);
			var radius: Number = width / 2;
			graphics.drawCircle(x + radius, y + radius, radius);
			if (style.fill_color) this.graphics.endFill();
		}
		
		public function draw_arrow(x: int, y: int, width: int, height: int, style:*): void {
			begin2(style);
			if ((style.orientation == TOP) || !style.orientation) { // Вверх
				this.graphics.moveTo(x + width / 2, y);
				this.graphics.lineTo(x + width, y + height);
				this.graphics.lineTo(x, y + height);	
				this.graphics.lineTo(x + width / 2, y);
			} else if (style.orientation == RIGHT) { // Вправо
				this.graphics.moveTo(x, y);
				this.graphics.lineTo(x + width, y + height / 2);
				this.graphics.lineTo(x, y + height);
				this.graphics.lineTo(x, y);
			} else if (style.orientation == BOTTOM) {	// Вниз
				this.graphics.moveTo(x, y);
				this.graphics.lineTo(x + width, y);
				this.graphics.lineTo(x + width / 2, y + height);
				this.graphics.lineTo(x, y);
			} else if (style.orientation == LEFT) {	// Налево
				this.graphics.moveTo(x, y + height / 2);
				this.graphics.lineTo(x + width, y);
				this.graphics.lineTo(x + width, y + height);
				this.graphics.lineTo(x, y + height / 2);
			}
			if (style.fill_color) this.graphics.endFill();
		}
		
		public function drawPath(x: int, y: int, width: int, height: int, style:*): void {
			var drawData: Object = getDrawPath();
			if (drawData) {
				begin2(style);
				graphics.drawPath(drawData.commands, drawData.data, drawData.winding);
				if (style.fill_color) this.graphics.endFill();
			}
		}
		
		protected function getDrawPath(): Object {
			return null;
		}
		
		public function drawStar(r1: Number, r2: Number, rays: int, px: Number=0, py:Number=0): void {
			uif_util.drawStar(graphics, r1, r2, rays, px, py);
		}		
	
		protected function begin2(style: Object): void {
			begin(style.line_width, style.line_color,
				  style.line_alpha, style.fill_color,
				  style.fill_alpha);
/*			if (style.filters) {
				for (var i: String in style.filters) 
					this[i](style.filters[i]);
			}*/
		}
		
		protected function applyFillStyle(fill_color: Object): void {
			var matrix: Matrix = new Matrix();
			var rotate: Number = fill_color.rotation?fill_color.rotation:0;
			var colors: Array = fill_color.colors?fill_color.colors:[0, 0xFFFFFF];
			var ratios: Array;
			var alphas: Array;
			var i: int;
			if (!fill_color.ratios) {
				ratios = new Array();
				for (i=0;i<colors.length;i++) ratios[i] = 0xFF * i/(colors.length-1); 
			} else ratios = fill_color.ratios;
			
			if (!fill_color.alphas) {
				alphas = new Array();
				for (i=0;i<colors.length;i++) alphas[i] = 1; 
			} else alphas = fill_color.alphas;
			
			var spreadMethod: String = fill_color.spreadMethod?fill_color.spreadMethod:SpreadMethod.PAD;
			var focalPointRatio: Number = fill_color.focalPointRatio?fill_color.focalPointRatio:0;
			
			var type: String = fill_color.type?fill_color.type:GradientType.LINEAR;
			var m_width: int = fill_color.width?fill_color.width:width;
			var m_height: int = fill_color.height?fill_color.height:height;
			var tx:int = fill_color.tx?(fill_color.tx * m_width):0;
			var ty:int = fill_color.ty?(fill_color.ty * m_height):0;

			var interpolationMethod: String = fill_color.interpolationMethod?fill_color.interpolationMethod:InterpolationMethod.RGB;
			matrix.createGradientBox(m_width, m_height, rotate, tx, ty);
			graphics.beginGradientFill(type, colors, alphas, 
				ratios, matrix, spreadMethod, 
				interpolationMethod, focalPointRatio);
		}
		
		protected function begin(line_width: int, line_color: int, line_alpha: *=1, fill_color: *=undefined, fill_alpha: *=undefined): void {
			if (fill_color != undefined) {
				if (typeof(fill_color) == 'object') applyFillStyle(fill_color) 
				else if (fill_alpha != undefined) this.graphics.beginFill(fill_color as int, fill_alpha);
			}
			if (line_width) {
				if (line_alpha == undefined) line_alpha = 100;
				this.graphics.lineStyle(line_width, line_color, line_alpha, true, 'none', 'round', 'miter', 4);
			}
		}		

		protected function shadow(style: Object): void {
			var options: Object = union({
				distance: 10, 
				angle: 45, 
				color: 0,
				alpha: 0.8,
				blurX: 3,
				blurY: 3,
				quality: 3,
				inner: false,
				knockout: false,
				hideObject: false,
				strength: 1
			}, style);
			if (!shadow_filter) {
				shadow_filter = new DropShadowFilter(options.distance, 
															options.angle, 
															options.color, 
															options.alpha, 
															options.blurX, 
															options.blurY, 
															options.strength, 
															options.quality, 
															options.inner, 
															options.knockout, 
															options.hideObject);
				addFilter(shadow_filter);
			} else applyOptions(shadow_filter, options);
			this.filters = filterArray;
		}
		
		protected function blur(style: Object): void {
			var options: Object = union({
				blurX: 2,
				blurY: 2,
				quality: 3
			}, style);
			if (!blur_filter) {
				blur_filter = new BlurFilter(options.blurX, options.blurY, options.quality);
				addFilter(blur_filter);
			} else applyOptions(blur_filter, options);
			this.filters = filterArray;
		}
		
		protected function bevel(style: Object): void {
			var options: Object = union({
				distance: 2,
				angle: 45,
				highlightColor: 0xFFFFFF,
				highlightAlpha: .8,
				shadowColor: 0x000000,
				shadowAlpha: .8,
				blurX: 5,
				blurY: 5,
				type: "inner",
				strength: 5,
				quality: 3,
				knockout: false
			}, style);
			
			if (!bevel_filter) {
				bevel_filter = new BevelFilter(options.distance, 
												options.angle, 
												options.highlightColor, 
												options.highlightAlpha, 
												options.shadowColor, 
												options.shadowAlpha, 
												options.blurX, 
												options.blurY, 
												options.strength, 
												options.quality, 
												options.type, 
												options.knockout);
				addFilter(bevel_filter);
			} else applyOptions(bevel_filter, options);
			
			this.filters = filterArray;
		}

		protected function glow(style: Object): void {
			var options: Object = union({
				color: 0,
				alpha: 1,
				blurX: 2,
				blurY: 2,
				strength: 2,
				quality: 3,
				inner: false,
				knockout: false
			}, style);
			if (!glow_filter) {
				glow_filter = new GlowFilter(options.color, options.alpha, options.blurX, options.blurY, options.strength, options.quality, options.inner, options.knockout);
				addFilter(glow_filter);
			} else applyOptions(glow_filter, options);
			this.filters = filterArray;
		}
		
		public function addFilter(filter: BitmapFilter): void {
			filterArray.push(filter);
			this.filters = filterArray;
		}
   
		public function removeFilter(filter: BitmapFilter): void {
			for (var i:String in filterArray)
				if (filterArray[i] == filter) {
					filterArray.splice(Number(i), 1);
					this.filters = filterArray;
				}
		}

		public function clearFilters(): void {
			shadow_filter = null;
			blur_filter = null;
			bevel_filter = null;
			glow_filter = null;
			filterArray.splice(0, filterArray.length);
			filters = [];
		}
	}

}